/*********************************************************************************************************************
 * COPYRIGHT NOTICE
 * Copyright (c) 2018,逐飞科技
 * All rights reserved.
 * 技术讨论QQ群：	一群：179029047(已满)
 *					二群：244861897(已满)
 *					三群：824575535
 *
 * 以下所有内容版权均属逐飞科技所有，未经允许不得用于商业用途，
 * 欢迎各位使用并传播本程序，修改内容时必须保留逐飞科技的版权声明。
 *
 * @file			zf_iic.c
 * @company			成都逐飞科技有限公司
 * @author			逐飞科技(QQ3184284598)
 * @version			查看doc内version文件 版本说明
 * @Software		IAR 8.3 or MDK 5.24
 * @Taobao			https://seekfree.taobao.com/
 * @date			2020-03-25
 * @note			本文件作为 LPC55S 系列芯片开源库外设文件
					提供 iic 驱动
 ********************************************************************************************************************/
#include "zf_iic.h"
#include "zf_isr.h"

i2c_master_handle_t g_iic_master_transfer_handle[8];
i2c_slave_handle_t g_iic_slave_transfer_handle[8];

//-------------------------------------------------------------------------------------------------------------------
//	@brief		获取 IIC MASTER 默认设置
//	@param		config			配置参数结构体
//	Sample usage:				zf_iic_master_get_default_config( &config );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_master_get_default_config (i2c_master_config_t *config)
{
	assert(config != NULL);
	I2C_MasterGetDefaultConfig(config);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		修改 IIC MASTER 设置
//	@param		config			FC所选功能的配置参数结构体
//	@param		param_index		选择参数
//	@param		data			数据
//	Sample usage:				zf_iic_master_param_set( &config, IIC_MASTER_PARAM_BAUD_RATE, 100000U );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_master_param_set  (i2c_master_config_t *config, iic_master_param_list param_index, uint32_t data)
{
	assert(config != NULL);
	switch(param_index)
	{
		case IIC_MASTER_PARAM_MASTER_ENABLE :
			config->enableMaster = (bool) data;
			break;
		case IIC_MASTER_PARAM_BAUD_RATE :
			config->baudRate_Bps = data;
			break;
		case IIC_MASTER_PARAM_TIMEOUT_ENABLE :
			config->enableTimeout = (bool) data;
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		获取 IIC MASTER TRANSFER 默认设置
//	@param		config			配置参数结构体
//	Sample usage:				zf_iic_master_get_default_transfer_config( &config );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_master_get_default_transfer_config (i2c_master_transfer_t *config)
{
	config->flags			= IIC_TRANSFER_FLAG_DEFAULT;
	config->slaveAddress	= 0x7EU;
	config->direction		= (i2c_direction_t)IIC_TRANSFER_DIR_WRITE;
	config->subaddress		= 0x01;
	config->subaddressSize	= 0;
	config->data			= NULL;
	config->dataSize		= 0;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		设置 IIC 传输结构体的参数
//	@param		config			配置参数结构体
//	@param		param_index		所选配置参数
//	@param		data			参数
//	Sample usage:				zf_iic_master_transfer_param_set(&config, IIC_TRANSFER_PARAM_TRANSFER_FLAG, IIC_TRANSFER_FLAG_DEFAULT);
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_master_transfer_param_set  (i2c_master_transfer_t *config, iic_master_transfer_param_list param_index, uint32_t data)
{
	assert(config != NULL);
	switch(param_index)
	{
		case IIC_TRANSFER_PARAM_TRANSFER_FLAG :
			config->flags = (iic_transfer_flag_list)data;
			break;
		case IIC_TRANSFER_PARAM_SLAVE_ADDRESS :
			config->slaveAddress = data;
			break;
		case IIC_TRANSFER_PARAM_DATA_DIR :
			config->direction = (i2c_direction_t) data;
			break;
		case IIC_TRANSFER_PARAM_SUB_ADDRESS :
			config->subaddress = (bool) data;
			break;
		case IIC_TRANSFER_PARAM_SUBADD_SIZE :
			config->subaddressSize = data;
			break;
//		case IIC_TRANSFER_PARAM_DATA_BUFFER :
//			config->data = (void *)data;
//			break;
		case IIC_TRANSFER_PARAM_DATA_LEN :
			config->dataSize = data;
			break;
		default:
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		设置 IIC 传输结构体的数据缓冲区
//	@param		config			配置参数结构体
//	@param		data			缓冲区指针
//	Sample usage:				zf_iic_master_transfer_buffer_set(&config, &data_buffer);
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_master_transfer_buffer_set (i2c_master_transfer_t *config, void *data)
{
	config->data = data;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		获取 IIC SLAVE 默认设置
//	@param		config			配置参数结构体
//	Sample usage:				zf_iic_slave_get_default_config( &config );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_slave_get_default_config (i2c_slave_config_t *config)
{
	assert(config != NULL);
	I2C_SlaveGetDefaultConfig(config);

	config->address0.address = 0x7EU;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		修改 IIC SLAVE 设置
//	@param		config			配置参数结构体
//	@param		param_index		选择参数
//	@param		data			数据
//	Sample usage:				zf_iic_slave_param_set( &config, IIC_SLAVE_PARAM_SLAVE_ENABLE, true );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_slave_param_set  (i2c_slave_config_t *config, iic_slave_param_list param_index, uint8_t data)
{
	assert(config != NULL);
	switch(param_index)
	{
		case IIC_SLAVE_PARAM_ADDRESS_0 :
			config->address0.address = (uint8_t) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_0_MASK :
			config->address0.addressDisable = (bool) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_1 :
			config->address1.address = (uint8_t) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_1_MASK :
			config->address1.addressDisable = (bool) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_2 :
			config->address2.address = (uint8_t) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_2_MASK :
			config->address2.addressDisable = (bool) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_3 :
			config->address3.address = (uint8_t) data;
			break;
		case IIC_SLAVE_PARAM_ADDRESS_3_MASK :
			config->address3.addressDisable = (bool) data;
			break;
		case IIC_SLAVE_PARAM_QUAL_MODE :
			config->qualMode = (i2c_slave_address_qual_mode_t) data;
			break;
		case IIC_SLAVE_PARAM_QUAL_ADDRESS :
			config->qualAddress = (uint8_t) data;
			break;
		case IIC_SLAVE_PARAM_SPEED_MODE :
			config->busSpeed = (i2c_slave_bus_speed_t) data;
			break;
		case IIC_SLAVE_PARAM_SLAVE_ENABLE :
			config->enableSlave = (bool) data;
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		建立 IIC MASTER TRANSFER 传输句柄
//	@param		index			iic 索引
//	@param		callback		用户回调函数
//	Sample usage:				zf_iic_master_transfer_great_handle(IIC_INDEX0, callback);
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_master_transfer_great_handle (flexcomm_index_list index, i2c_master_transfer_callback_t callback)
{
	assert(callback != NULL);
	I2C_MasterTransferCreateHandle(iic_index[index], &g_iic_master_transfer_handle[index], callback, NULL);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		建立 IIC SLAVE TRANSFER 传输句柄
//	@param		index			iic 索引
//	@param		callback		用户回调函数
//	Sample usage:				zf_iic_slave_transfer_great_handle(IIC_INDEX0, callback);
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_slave_transfer_great_handle (flexcomm_index_list index, i2c_slave_transfer_callback_t callback)
{
	assert(callback != NULL);
	I2C_SlaveTransferCreateHandle( iic_index[index], &g_iic_slave_transfer_handle[index], callback, NULL);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC MASTER TRANSFER 传输数据
//	@param		index			iic 索引
//	@param		config			TRANSFER 配置参数结构体
//	Sample usage:				zf_iic_master_transfer_non_blocking(IIC_INDEX0, config);
//-------------------------------------------------------------------------------------------------------------------
uint32_t zf_iic_master_transfer_non_blocking (flexcomm_index_list index, i2c_master_transfer_t *config)
{
	return I2C_MasterTransferNonBlocking (iic_index[index], &g_iic_master_transfer_handle[index], config);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC SLAVE TRANSFER 传输数据
//	@param		index			iic 索引
//	@param		eventMask		回调的事件代码
//	Sample usage:				zf_iic_slave_transfer_non_blocking(IIC_INDEX0, callback);
//-------------------------------------------------------------------------------------------------------------------
uint32_t zf_iic_slave_transfer_non_blocking (flexcomm_index_list index, uint32_t eventMask)
{
	return I2C_SlaveTransferNonBlocking (iic_index[index], &g_iic_slave_transfer_handle[index], eventMask);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC MASTER 指定地址发送
//	@param		index			iic 索引
//	@param		address0		指定地址
//	@param		data			发送内容指针
//	@param		datalen			数据长度
//	@return		result			是否发送数据成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_master_send_data( IIC_INDEX0, ADDR, databuff, datalen );
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_master_send_data (flexcomm_index_list index, uint8_t address, uint8_t *data, size_t datalen)
{
	if (kStatus_Success == I2C_MasterStart( iic_index[index], address, kI2C_Write))
	{
		if (I2C_MasterWriteBlocking(iic_index[index], data, datalen, kI2C_TransferDefaultFlag) != kStatus_Success)
		{
			return 0;
		}
		if (I2C_MasterStop(iic_index[index]) != kStatus_Success)
		{
			return 0;
		}
	}
	else
	{
		return 0;
	}
	return 1;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC MASTER 指定地址接收
//	@param		index			iic 索引
//	@param		address0		指定地址
//	@param		data			接收内容指针
//	@param		datalen			数据长度
//	@return		result			是否发送数据成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_master_receive_data( IIC_INDEX0, ADDR, databuff, datalen );
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_master_receive_data (flexcomm_index_list index, uint8_t address, uint8_t *data, size_t datalen)
{
	if (kStatus_Success == I2C_MasterStart(iic_index[index], address, kI2C_Read))
	{
		if (I2C_MasterReadBlocking(iic_index[index], data, datalen, kI2C_TransferDefaultFlag) != kStatus_Success)
		{
			return 0;
		}
		if (I2C_MasterStop(iic_index[index]) != kStatus_Success)
		{
			return 0;
		}
	}
	else
	{
		return 0;
	}
	return 1;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC SLAVE 发送
//	@param		index			iic 索引
//	@param		data			发送内容指针
//	@param		datalen			数据长度
//	@return		result			是否发送数据成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_slave_send_data( IIC_INDEX0, databuff, datalen );
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_slave_send_data (flexcomm_index_list index, uint8_t *data, size_t datalen)
{
	if (I2C_SlaveWriteBlocking(iic_index[index], data, datalen) != kStatus_Success)
	{
		return 0;
	}
	return 1;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC SLAVE 接收
//	@param		index			iic 索引
//	@param		data			接收内容指针
//	@param		datalen			数据长度
//	@return		result			是否发送数据成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_slave_receive_data( IIC_INDEX0, databuff, datalen );	// MASTER接收数据
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_slave_receive_data (flexcomm_index_list index, uint8_t *data, size_t datalen)
{
	if (I2C_SlaveReadBlocking(iic_index[index], data, datalen) != kStatus_Success)
	{
		return 0;
	}
	return 1;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC 主机起始信号 读
//	@param		index			iic 索引
//	@param		address			目标地址
//	@return		result			是否成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_master_start_read(IIC_INDEX0, addr);
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_master_start_read (flexcomm_index_list index, uint8_t address)
{
	return (I2C_MasterStart(iic_index[index], address, kI2C_Read) == kStatus_Success);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC 主机起始信号 写
//	@param		index			iic 索引
//	@param		address			目标地址
//	@return		result			是否成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_master_start_write(IIC_INDEX0, addr);
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_master_start_write (flexcomm_index_list index, uint8_t address)
{
	return (I2C_MasterStart(iic_index[index], address, kI2C_Write) == kStatus_Success);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC 主机停止信号
//	@param		index			iic 索引
//	@return		result			是否成功 0-发送出错 1-发送成功
//	Sample usage:				zf_iic_master_stop(IIC_INDEX0);
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_iic_master_stop (flexcomm_index_list index)
{
	return (I2C_MasterStop(iic_index[index]) == kStatus_Success);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC 写寄存器 默认主机
//	@param		index			iic 索引
//	@param		add				外设地址
//	@param		reg				寄存器地址
//	@return		data			数据
//	Sample usage:				zf_iic_write_reg( IIC_INDEX0, 0x7e, 0x01, 0x00 );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_write_reg (flexcomm_index_list index, uint8_t add, uint8_t reg, uint8_t data)
{
	uint8_t data_buffer[2] = {reg,data};
	I2C_MasterStart( iic_index[index], add, kI2C_Write);
	I2C_MasterWriteBlocking( iic_index[index], data_buffer, 2, kI2C_TransferDefaultFlag);
	I2C_MasterStop( iic_index[index] );
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		IIC 读寄存器 默认主机
//	@param		index			iic 索引
//	@param		add				外设地址
//	@param		reg				寄存器地址
//	@return		data			数据缓冲区
//	@return		datalen			数据长度
//	Sample usage:				zf_iic_write_reg( IIC_INDEX0, 0x7e, &data_buffer, 16 );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_read_reg (flexcomm_index_list index, uint8_t add, uint8_t reg, uint8_t *data, uint8_t datalen)
{
	uint8_t data_buffer = reg;
	I2C_MasterStart( iic_index[index], add, kI2C_Write);
	I2C_MasterWriteBlocking( iic_index[index], &data_buffer, 1, kI2C_TransferDefaultFlag);
	I2C_MasterStart( iic_index[index], add, kI2C_Read);
	I2C_MasterReadBlocking( iic_index[index], data, datalen, kI2C_TransferDefaultFlag);
	I2C_MasterStop( iic_index[index] );
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		打开对应 FlexCOMM 端口中断使能
//	@param		flexCommIndex	所选 FC 标识
//	@param		handler(void)	指定的自拟定中断服务函数
//	Sample usage:				zf_spi_interrupt_enable( FLEX_COMM0, SPI_IRQHandler );
//-------------------------------------------------------------------------------------------------------------------
void zf_iic_interrupt_enable (flexcomm_index_list flexCommIndex, void handler(void))
{
	assert(flexCommIndex <= 7 && handler != NULL);
	flexcomm_irqn_func[flexCommIndex] = handler;
	EnableIRQ(flexcomm_irqn[flexCommIndex]);
}

